package com.spark.sniffer.plugin.plugins.interceptor;

import java.lang.reflect.Method;

import com.spark.sniffer.constant.PassThroughEnum;
import com.spark.sniffer.logging.api.Logger;
import com.spark.sniffer.logging.api.LoggerFactory;
import com.spark.sniffer.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
import com.spark.sniffer.plugin.interceptor.enhance.MethodInterceptResult;
import com.spark.sniffer.tracing.TraceId;
import com.spark.sniffer.tracing.TracingContext;
import com.spark.sniffer.util.ReflectUtil;
import com.spark.sniffer.util.ReflectUtil.WrapperMethod;

/**
 * Note：Shiro的处理在DispatcherServlet之前
 * 
 * @author cobe
 *
 */
public class ShiroFilterInterceptor implements InstanceMethodsAroundInterceptor {
    private static final Logger log = LoggerFactory.getLogger(ShiroFilterInterceptor.class);

    @Override
    public void beforeMethod(Object instance, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
        MethodInterceptResult result) throws Throwable {
        // HttpServletRequest request = (HttpServletRequest)allArguments[0];
        // HttpServletResponse response = (HttpServletResponse)allArguments[1];

        getAndPutPassThroughsToContext(allArguments);
    }

    @Override
    public Object afterMethod(Object instance, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
        Object ret) throws Throwable {
        return ret;
    }

    @Override
    public void handleMethodException(Object instance, Method method, Object[] allArguments, Class<?>[] argumentsTypes,
        Throwable t) {}

    /**
     * @param allArguments
     */
    private void getAndPutPassThroughsToContext(Object[] allArguments) {
        WrapperMethod getHeaderMethod = ReflectUtil.getMethod(allArguments[0], "getHeader", String.class);

        // 从header中获取透传数据设置到上下文中
        for (PassThroughEnum passThrough : PassThroughEnum.values()) {
            String key = passThrough.getValue();
            String value = getHeaderMethod.invoke(key);

            // traceid特别处理
            if (TraceId.KEY.equals(key)) {
                if (value == null) {
                    value = TraceId.generate();
                }
                TraceId.putToContext(value);

                // 将traceid设置到response.header[traceid]中，以便回显在调用端
                ReflectUtil.getMethod(allArguments[1], "setHeader", String.class, String.class).invoke(TraceId.KEY,
                    value);
            }

            if (value == null || value.trim().equals("")) {
                continue;
            }

            TracingContext.getContext().putPassThrough(key, value);
            log.debug("put passThrough on shiro to context: {}={}", key, value);
        }
    }
}
